#include "RabbitMQReceiver.h"

RabbitMQReceiver::RabbitMQReceiver(QObject* parent)
    : QObject(parent)
{
}

RabbitMQReceiver::~RabbitMQReceiver()
{
    stop();
}

void RabbitMQReceiver::setHost(QString host, int port, QString virHost, QString userName, QString pw)
{
    m_info.connection.hostName = host;
    m_info.connection.port = port;
    m_info.connection.virHost = virHost;
    m_info.connection.userName = userName;
    m_info.connection.userPassword = pw;
}

void RabbitMQReceiver::stop()
{
    if (m_isStart) {
        m_client.setAutoReconnect(false);
        m_client.disconnectFromHost();
        m_isStart = false;
    }
}

void RabbitMQReceiver::start(QString exchange, QString queueName, QStringList bindingkeys)
{
    if (m_isStart == true) {
        qDebug() << "has started!";
        return;
    }

    m_isStart = true;
    m_client.setUsername(m_info.connection.userName);
    m_client.setPassword(m_info.connection.userPassword);
    m_client.setVirtualHost(m_info.connection.virHost);
    m_client.setAutoReconnect(true);
    m_info.bindingkeys = bindingkeys;

    m_info.queue.name = queueName;
    m_info.exchange.name = exchange;

    connect(&m_client, &QAmqpClient::connected, this, &RabbitMQReceiver::clientConnected);
    connect(&m_client, &QAmqpClient::disconnected, this, &RabbitMQReceiver::clientDisconnected);
    connect(&m_client, SIGNAL(error(QAMQP::Error)), this, SLOT(on_error(QAMQP::Error)));
    m_client.connectToHost(QHostAddress(m_info.connection.hostName), m_info.connection.port);
}

void RabbitMQReceiver::on_error(QAMQP::Error error)
{
    qDebug() << "mq-error: " << error << m_client.errorString();
}

void RabbitMQReceiver::clientConnected()
{
    qDebug() << __FUNCTION__;
    QAmqpExchange* topic_logs = m_client.createExchange(m_info.exchange.name);
    m_exchange = topic_logs;
    connect(topic_logs, SIGNAL(declared()), this, SLOT(exchangeDeclared()));
    topic_logs->declare(QAmqpExchange::Topic, QAmqpExchange::ExchangeOption::NoOptions);

    // exchangeDeclared();
    // queueDeclared();
}

void RabbitMQReceiver::clientDisconnected()
{
    qDebug() << "disconnected";
}

void RabbitMQReceiver::exchangeDeclared()
{
    qDebug() << __FUNCTION__ << ",queue-name:" << m_info.queue.name;
    QAmqpQueue* temporaryQueue = m_client.createQueue(m_info.queue.name);
    connect(temporaryQueue, SIGNAL(declared()), this, SLOT(queueDeclared()));
    connect(temporaryQueue, SIGNAL(bound()), this, SLOT(queueBound()));
    connect(temporaryQueue, SIGNAL(messageReceived()), this, SLOT(messageReceived()));
    temporaryQueue->declare(QAmqpQueue::NoOptions);
}

void RabbitMQReceiver::queueDeclared()
{
    qDebug() << __FUNCTION__;
    QAmqpQueue* temporaryQueue = qobject_cast<QAmqpQueue*>(sender());
    if (!temporaryQueue)
        return;

    foreach (QString bindingKey, m_info.bindingkeys)
        temporaryQueue->bind(m_info.exchange.name, bindingKey);
    qDebug() << " [*] Waiting for logs. To exit press CTRL+C";
}

void RabbitMQReceiver::queueBound()
{
    QAmqpQueue* temporaryQueue = qobject_cast<QAmqpQueue*>(sender());
    if (!temporaryQueue)
        return;
    temporaryQueue->consume(QAmqpQueue::coNoAck);
}

void RabbitMQReceiver::messageReceived()
{
    QAmqpQueue* temporaryQueue = qobject_cast<QAmqpQueue*>(sender());
    if (!temporaryQueue)
        return;

    QAmqpMessage message = temporaryQueue->dequeue();
    qDebug() << " [x] " << message.routingKey() << ":" << message.payload();
    emit recv_msg(message.routingKey(), message.payload());

    // publish("report_mq", "get !!!!!");
}

void RabbitMQReceiver::publish(QString routingkey, QString msg)
{
    if (m_client.isConnected()) {
        if (m_exchange) {
            m_exchange->publish(msg, routingkey);
        }
    }
}
